home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / misc / amicvs1-0.lha / AmiCVS / scr / subr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-01  |  18.1 KB  |  913 lines

  1. /*
  2.  * Copyright (c) 1992, Brian Berliner and Jeff Polk
  3.  * Copyright (c) 1989-1992, Brian Berliner
  4.  * 
  5.  * You may distribute under the terms of the GNU General Public License as
  6.  * specified in the README file that comes with the CVS 1.3 kit.
  7.  * 
  8.  * Various useful functions for the CVS support code.
  9.  */
  10.  
  11. #include "cvs.h"
  12.  
  13. #ifdef _MINIX
  14. #undef    POSIX        /* Minix 1.6 doesn't support POSIX.1 sigaction yet */
  15. #endif
  16.  
  17. #ifndef VPRINTF_MISSING
  18. #if __STDC__
  19. #include <stdarg.h>
  20. #define VA_START(args, lastarg) va_start(args, lastarg)
  21. #else
  22. #include <varargs.h>
  23. #define VA_START(args, lastarg) va_start(args)
  24. #endif
  25. #else
  26. #define va_alist a1, a2, a3, a4, a5, a6, a7, a8
  27. #define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
  28. #endif
  29.  
  30. #ifndef lint
  31. static char rcsid[] = "@(#)subr.c 1.52 92/03/31";
  32. #endif
  33.  
  34. #if __STDC__
  35. static void run_add_arg (char *s);
  36. static void run_init_prog (void);
  37. #else
  38. static void run_add_arg ();
  39. static void run_init_prog ();
  40. #endif                /* __STDC__ */
  41.  
  42. extern char *getlogin ();
  43. extern char *strtok ();
  44.  
  45. /*
  46.  * Copies "from" to "to". mallocs a buffer large enough to hold the entire
  47.  * file and does one read/one write to do the copy.  This is reasonable,
  48.  * since source files are typically not too large.
  49.  */
  50. void
  51. copy_file (from, to)
  52.     char *from;
  53.     char *to;
  54. {
  55.     struct stat sb;
  56.     struct utimbuf t;
  57.     int fdin, fdout;
  58.     char *buf;
  59.  
  60.     if (trace)
  61.     (void) fprintf (stderr, "-> copy(%s,%s)\n", from, to);
  62.     if (noexec)
  63.     return;
  64.  
  65.     if ((fdin = open (from, O_RDONLY)) < 0)
  66.     error (1, errno, "cannot open %s for copying", from);
  67.     if (fstat (fdin, &sb) < 0)
  68.     error (1, errno, "cannot fstat %s", from);
  69.     if ((fdout = creat (to, (int) sb.st_mode & 07777)) < 0)
  70.     error (1, errno, "cannot create %s for copying", to);
  71.     if (sb.st_size > 0)
  72.     {
  73.     buf = xmalloc ((int) sb.st_size);
  74.     if (read (fdin, buf, (int) sb.st_size) != (int) sb.st_size)
  75.         error (1, errno, "cannot read file %s for copying", from);
  76.     if (write (fdout, buf, (int) sb.st_size) != (int) sb.st_size
  77. #ifndef FSYNC_MISSING
  78.         || fsync (fdout) == -1
  79. #endif
  80.         )
  81.     {
  82.         error (1, errno, "cannot write file %s for copying", to);
  83.     }
  84.     free (buf);
  85.     }
  86.     (void) close (fdin);
  87.     if (close (fdout) < 0)
  88.     error (1, errno, "cannot close %s", to);
  89.  
  90.     /* now, set the times for the copied file to match those of the original */
  91.     t.actime = sb.st_atime;
  92.     t.modtime = sb.st_mtime;
  93.     (void) utime (to, &t);
  94. }
  95.  
  96. /*
  97.  * Returns non-zero if the argument file is a directory, or is a symbolic
  98.  * link which points to a directory.
  99.  */
  100. int
  101. isdir (file)
  102.     char *file;
  103. {
  104.     struct stat sb;
  105.  
  106.     if (stat (file, &sb) < 0)
  107.     return (0);
  108.     return (S_ISDIR (sb.st_mode));
  109. }
  110.  
  111. /*
  112.  * Returns non-zero if the argument file is a symbolic link.
  113.  */
  114. int
  115. islink (file)
  116.     char *file;
  117. {
  118. #ifdef S_ISLNK
  119.     struct stat sb;
  120.  
  121.     if (lstat (file, &sb) < 0)
  122.     return (0);
  123.     return (S_ISLNK (sb.st_mode));
  124. #else
  125.     return (0);
  126. #endif
  127. }
  128.  
  129. /*
  130.  * Returns non-zero if the argument file exists.
  131.  */
  132. int
  133. isfile (file)
  134.     char *file;
  135. {
  136.     struct stat sb;
  137.  
  138.     if (stat (file, &sb) < 0)
  139.     return (0);
  140.     return (1);
  141. }
  142.  
  143. /*
  144.  * Returns non-zero if the argument file is readable.
  145.  * XXX - must be careful if "cvs" is ever made setuid!
  146.  */
  147. int
  148. isreadable (file)
  149.     char *file;
  150. {
  151.     return (access (file, R_OK) != -1);
  152. }
  153.  
  154. /*
  155.  * Returns non-zero if the argument file is writable
  156.  * XXX - muct be careful if "cvs" is ever made setuid!
  157.  */
  158. int
  159. iswritable (file)
  160.     char *file;
  161. {
  162.     return (access (file, W_OK) != -1);
  163. }
  164.  
  165. /*
  166.  * Open a file and die if it fails
  167.  */
  168. FILE *
  169. open_file (name, mode)
  170.     char *name;
  171.     char *mode;
  172. {
  173.     FILE *fp;
  174.  
  175.     if ((fp = fopen (name, mode)) == NULL)
  176.     error (1, errno, "cannot open %s", name);
  177.     return (fp);
  178. }
  179.  
  180. /*
  181.  * Open a file if allowed and return.
  182.  */
  183. FILE *
  184. Fopen (name, mode)
  185.     char *name;
  186.     char *mode;
  187. {
  188.     if (trace)
  189.     (void) fprintf (stderr, "-> fopen(%s,%s)\n", name, mode);
  190.     if (noexec)
  191.     return (NULL);
  192.  
  193.     return (fopen (name, mode));
  194. }
  195.  
  196. /*
  197.  * Make a directory and die if it fails
  198.  */
  199. void
  200. make_directory (name)
  201.     char *name;
  202. {
  203.     struct stat buf;
  204.  
  205.     if (stat (name, &buf) == 0)
  206.     {
  207.     if (S_ISDIR (buf.st_mode))
  208.     {
  209.         if (access (name, (R_OK | W_OK | X_OK)) == 0)
  210.         {
  211.         error (0, 0, "Directory %s already exists", name);
  212.         return;
  213.         }
  214.         else
  215.         {
  216.         error (0, 0,
  217.             "Directory %s already exists but is protected from you",
  218.                name);
  219.         }
  220.     }
  221.     else
  222.         error (0, 0, "%s already exists but is not a directory", name);
  223.     }
  224.     if (!noexec && mkdir (name, 0777) < 0)
  225.     error (1, errno, "cannot make directory %s", name);
  226. }
  227.  
  228. /*
  229.  * Make a path to the argument directory, printing a message if something
  230.  * goes wrong.
  231.  */
  232. void
  233. make_directories (name)
  234.     char *name;
  235. {
  236.     char *cp;
  237.  
  238.     if (noexec)
  239.     return;
  240.  
  241.     if (mkdir (name, 0777) == 0 || errno == EEXIST)
  242.     return;
  243.     if (errno != ENOENT)
  244.     {
  245.     error (0, errno, "cannot make path to %s", name);
  246.     return;
  247.     }
  248.     if ((cp = rindex (name, '/')) == NULL)
  249.     return;
  250.     *cp = '\0';
  251.     make_directories (name);
  252.     *cp++ = '/';
  253.     if (*cp == '\0')
  254.     return;
  255.     (void) mkdir (name, 0777);
  256. }
  257.  
  258. /*
  259.  * malloc some data and die if it fails
  260.  */
  261. char *
  262. xmalloc (bytes)
  263.     int bytes;
  264. {
  265.     char *cp;
  266.  
  267.     if (bytes <= 0)
  268.     error (1, 0, "bad malloc size %d", bytes);
  269.     if ((cp = malloc ((unsigned) bytes)) == NULL)
  270.     error (1, 0, "malloc failed");
  271.     return (cp);
  272. }
  273.  
  274. /*
  275.  * realloc data and die if it fails [I've always wanted to have "realloc" do
  276.  * a "malloc" if the argument is NULL, but you can't depend on it.  Here, I
  277.  * can *force* it.
  278.  */
  279. char *
  280. xrealloc (ptr, bytes)
  281.     char *ptr;
  282.     int bytes;
  283. {
  284.     char *cp;
  285.  
  286.     if (!ptr)
  287.     return (xmalloc (bytes));
  288.  
  289.     if (bytes <= 0)
  290.     error (1, 0, "bad realloc size %d", bytes);
  291.     if ((cp = realloc (ptr, (unsigned) bytes)) == NULL)
  292.     error (1, 0, "realloc failed");
  293.     return (cp);
  294. }
  295.  
  296. /*
  297.  * Duplicate a string, calling xmalloc to allocate some dynamic space
  298.  */
  299. char *
  300. xstrdup (str)
  301.     char *str;
  302. {
  303.     char *s;
  304.  
  305.     if (str == NULL)
  306.     return ((char *) NULL);
  307.     s = xmalloc (strlen (str) + 1);
  308.     (void) strcpy (s, str);
  309.     return (s);
  310. }
  311.  
  312. /*
  313.  * Change the mode of a file, either adding write permissions, or removing
  314.  * all write permissions.  Adding write permissions honors the current umask
  315.  * setting.
  316.  */
  317. void
  318. xchmod (fname, writable)
  319.     char *fname;
  320.     int writable;
  321. {
  322.     struct stat sb;
  323.     int mode, oumask;
  324.  
  325.     if (stat (fname, &sb) < 0)
  326.     {
  327.     if (!noexec)
  328.         error (0, errno, "cannot stat %s", fname);
  329.     return;
  330.     }
  331.     if (writable)
  332.     {
  333.     oumask = umask (0);
  334.     (void) umask (oumask);
  335.     mode = sb.st_mode | ((S_IWRITE | S_IWGRP | S_IWOTH) & ~oumask);
  336.     }
  337.     else
  338.     {
  339.     mode = sb.st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH);
  340.     }
  341.  
  342.     if (trace)
  343.     (void) fprintf (stderr, "-> chmod(%s,%o)\n", fname, mode);
  344.     if (noexec)
  345.     return;
  346.  
  347.     if (chmod (fname, mode) < 0)
  348.     error (0, errno, "cannot change mode of file %s", fname);
  349. }
  350.  
  351. /*
  352.  * Rename a file and die if it fails
  353.  */
  354. void
  355. rename_file (from, to)
  356.     char *from;
  357.     char *to;
  358. {
  359.     if (trace)
  360.     (void) fprintf (stderr, "-> rename(%s,%s)\n", from, to);
  361.     if (noexec)
  362.     return;
  363.  
  364.     if (rename (from, to) < 0)
  365.     error (1, errno, "cannot rename file %s to %s", from, to);
  366. }
  367.  
  368. /*
  369.  * link a file, if possible.
  370.  */
  371. int
  372. link_file (from, to)
  373.     char *from, *to;
  374. {
  375.     if (trace)
  376.     (void) fprintf (stderr, "-> link(%s,%s)\n", from, to);
  377.     if (noexec)
  378.     return (0);
  379.  
  380.     return (link (from, to));
  381. }
  382.  
  383. /*
  384.  * unlink a file, if possible.
  385.  */
  386. int
  387. unlink_file (f)
  388.     char *f;
  389. {
  390.     if (trace)
  391.     (void) fprintf (stderr, "-> unlink(%s)\n", f);
  392.     if (noexec)
  393.     return (0);
  394.  
  395.     return (unlink (f));
  396. }
  397.  
  398. /*
  399.  * Compare "file1" to "file2". Return non-zero if they don't compare exactly.
  400.  * 
  401.  * mallocs a buffer large enough to hold the entire file and does two reads to
  402.  * load the buffer and calls bcmp to do the cmp. This is reasonable, since
  403.  * source files are typically not too large.
  404.  */
  405. int
  406. xcmp (file1, file2)
  407.     char *file1;
  408.     char *file2;
  409. {
  410.     register char *buf1, *buf2;
  411.     struct stat sb;
  412.     off_t size;
  413.     int ret, fd1, fd2;
  414.  
  415.     if ((fd1 = open (file1, O_RDONLY)) < 0)
  416.     error (1, errno, "cannot open file %s for comparing", file1);
  417.     if ((fd2 = open (file2, O_RDONLY)) < 0)
  418.     error (1, errno, "cannot open file %s for comparing", file2);
  419.     if (fstat (fd1, &sb) < 0)
  420.     error (1, errno, "cannot fstat %s", file1);
  421.     size = sb.st_size;
  422.     if (fstat (fd2, &sb) < 0)
  423.     error (1, errno, "cannot fstat %s", file2);
  424.     if (size == sb.st_size)
  425.     {
  426.     if (size == 0)
  427.         ret = 0;
  428.     else
  429.     {
  430.         buf1 = xmalloc ((int) size);
  431.         buf2 = xmalloc ((int) size);
  432.         if (read (fd1, buf1, (int) size) != (int) size)
  433.         error (1, errno, "cannot read file %s cor comparing", file1);
  434.         if (read (fd2, buf2, (int) size) != (int) size)
  435.         error (1, errno, "cannot read file %s for comparing", file2);
  436.         ret = bcmp (buf1, buf2, (int) size);
  437.         free (buf1);
  438.         free (buf2);
  439.     }
  440.     }
  441.     else
  442.     ret = 1;
  443.     (void) close (fd1);
  444.     (void) close (fd2);
  445.     return (ret);
  446. }
  447.  
  448. /*
  449.  * Recover the space allocated by Find_Names() and line2argv()
  450.  */
  451. void
  452. free_names (pargc, argv)
  453.     int *pargc;
  454.     char *argv[];
  455. {
  456.     register int i;
  457.  
  458.     for (i = 0; i < *pargc; i++)
  459.     {                    /* only do through *pargc */
  460.     free (argv[i]);
  461.     }
  462.     *pargc = 0;                /* and set it to zero when done */
  463. }
  464.  
  465. /*
  466.  * Convert a line into argc/argv components and return the result in the
  467.  * arguments as passed.  Use free_names() to return the memory allocated here
  468.  * back to the free pool.
  469.  */
  470. void
  471. line2argv (pargc, argv, line)
  472.     int *pargc;
  473.     char *argv[];
  474.     char *line;
  475. {
  476.     char *cp;
  477.  
  478.     *pargc = 0;
  479.     for (cp = strtok (line, " \t"); cp; cp = strtok ((char *) NULL, " \t"))
  480.     {
  481.     argv[*pargc] = xstrdup (cp);
  482.     (*pargc)++;
  483.     }
  484. }
  485.  
  486. /*
  487.  * Returns the number of dots ('.') found in an RCS revision number
  488.  */
  489. int
  490. numdots (s)
  491.     char *s;
  492. {
  493.     char *cp;
  494.     int dots = 0;
  495.  
  496.     for (cp = s; *cp; cp++)
  497.     {
  498.     if (*cp == '.')
  499.         dots++;
  500.     }
  501.     return (dots);
  502. }
  503.  
  504. /*
  505.  * Get the caller's login from his uid. If the real uid is "root" try LOGNAME
  506.  * USER or getlogin(). If getlogin() and getpwuid() both fail, return
  507.  * the uid as a string.
  508.  */
  509. char *
  510. getcaller ()
  511. {
  512.     static char uidname[20];
  513.     struct passwd *pw;
  514.     char *name;
  515.     int uid;
  516.  
  517.     uid = getuid ();
  518.     if (uid == 0)
  519.     {
  520.     /* super-user; try getlogin() to distinguish */
  521.     if (((name = getenv("LOGNAME")) || (name = getenv("USER")) ||
  522.          (name = getlogin ())) && *name)
  523.         return (name);
  524.     }
  525.     if ((pw = (struct passwd *) getpwuid (uid)) == NULL)
  526.     {
  527.     (void) sprintf (uidname, "uid%d", uid);
  528.     return (uidname);
  529.     }
  530.     return (pw->pw_name);
  531. }
  532.  
  533. /*
  534.  * To exec a program under CVS, first call run_setup() to setup any initial
  535.  * arguments.  The options to run_setup are essentially like printf(). The
  536.  * arguments will be parsed into whitespace separated words and added to the
  537.  * global run_argv list.
  538.  * 
  539.  * Then, optionally call run_arg() for each additional argument that you'd like
  540.  * to pass to the executed program.
  541.  * 
  542.  * Finally, call run_exec() to execute the program with the specified arguments.
  543.  * The execvp() syscall will be used, so that the PATH is searched correctly.
  544.  * File redirections can be performed in the call to run_exec().
  545.  */
  546. static char *run_prog;
  547. static char **run_argv;
  548. static int run_argc;
  549. static int run_argc_allocated;
  550.  
  551. /* VARARGS */
  552. #if !defined (VPRINTF_MISSING) && __STDC__
  553. void 
  554. run_setup (char *fmt,...)
  555. #else
  556. void 
  557. run_setup (fmt, va_alist)
  558.     char *fmt;
  559.     va_dcl
  560.  
  561. #endif
  562. {
  563. #ifndef VPRINTF_MISSING
  564.     va_list args;
  565.  
  566. #endif
  567.     char *cp;
  568.     int i;
  569.  
  570.     run_init_prog ();
  571.  
  572.     /* clean out any malloc'ed values from run_argv */
  573.     for (i = 0; i < run_argc; i++)
  574.     {
  575.     if (run_argv[i])
  576.     {
  577.         free (run_argv[i]);
  578.         run_argv[i] = (char *) 0;
  579.     }
  580.     }
  581.     run_argc = 0;
  582.  
  583.     /* process the varargs into run_prog */
  584. #ifndef VPRINTF_MISSING
  585.     VA_START (args, fmt);
  586.     (void) vsprintf (run_prog, fmt, args);
  587.     va_end (args);
  588. #else
  589.     (void) sprintf (run_prog, fmt, a1, a2, a3, a4, a5, a6, a7, a8);
  590. #endif
  591.  
  592.     /* put each word into run_argv, allocating it as we go */
  593.     for (cp = strtok (run_prog, " \t"); cp; cp = strtok ((char *) NULL, " \t"))
  594.     run_add_arg (cp);
  595. }
  596.  
  597. void
  598. run_arg (s)
  599.     char *s;
  600. {
  601.     run_add_arg (s);
  602. }
  603.  
  604. /* VARARGS */
  605. #if !defined (VPRINTF_MISSING) && __STDC__
  606. void 
  607. run_args (char *fmt,...)
  608. #else
  609. void 
  610. run_args (fmt, va_alist)
  611.     char *fmt;
  612.     va_dcl
  613.  
  614. #endif
  615. {
  616. #ifndef VPRINTF_MISSING
  617.     va_list args;
  618.  
  619. #endif
  620.  
  621.     run_init_prog ();
  622.  
  623.     /* process the varargs into run_prog */
  624. #ifndef VPRINTF_MISSING
  625.     VA_START (args, fmt);
  626.     (void) vsprintf (run_prog, fmt, args);
  627.     va_end (args);
  628. #else
  629.     (void) sprintf (run_prog, fmt, a1, a2, a3, a4, a5, a6, a7, a8);
  630. #endif
  631.  
  632.     /* and add the (single) argument to the run_argv list */
  633.     run_add_arg (run_prog);
  634. }
  635.  
  636. static void
  637. run_add_arg (s)
  638.     char *s;
  639. {
  640.     /* allocate more argv entries if we've run out */
  641.     if (run_argc >= run_argc_allocated)
  642.     {
  643.     run_argc_allocated += 50;
  644.     run_argv = (char **) xrealloc ((char *) run_argv,
  645.                      run_argc_allocated * sizeof (char **));
  646.     }
  647.  
  648.     if (s)
  649.     run_argv[run_argc++] = xstrdup (s);
  650.     else
  651.     run_argv[run_argc] = (char *) 0;/* not post-incremented on purpose! */
  652. }
  653.  
  654. static void
  655. run_init_prog ()
  656. {
  657.     /* make sure that run_prog is allocated once */
  658.     if (run_prog == (char *) 0)
  659.     run_prog = xmalloc (10 * 1024);    /* 10K of args for _setup and _arg */
  660. }
  661.  
  662. int
  663. run_exec (stin, stout, sterr, flags)
  664.     char *stin;
  665.     char *stout;
  666.     char *sterr;
  667.     int flags;
  668. {
  669.     int shin, shout, sherr;
  670.     int mode_out, mode_err;
  671.     int status = -1;
  672.     int rerrno = 0;
  673.     int pid, w;
  674.  
  675. #ifdef POSIX
  676.     sigset_t sigset_mask, sigset_omask;
  677.     struct sigaction act, iact, qact;
  678.  
  679. #else
  680. #ifdef BSD_SIGNALS
  681.     int mask;
  682.     struct sigvec vec, ivec, qvec;
  683.  
  684. #else
  685.     SIGTYPE (*istat) (), (*qstat) ();
  686. #endif
  687. #endif
  688.  
  689.     if (trace)
  690.     {
  691.     (void) fprintf (stderr, "-> system(");
  692.     run_print (stderr);
  693.     (void) fprintf (stderr, ")\n");
  694.     }
  695.     if (noexec && (flags & RUN_REALLY) == 0)
  696.     return (0);
  697.  
  698.     /* make sure that we are null terminated, since we didn't calloc */
  699.     run_add_arg ((char *) 0);
  700.  
  701.     /* setup default file descriptor numbers */
  702.     shin = 0;
  703.     shout = 1;
  704.     sherr = 2;
  705.  
  706.     /* set the file modes for stdout and stderr */
  707.     mode_out = mode_err = O_WRONLY | O_CREAT;
  708.     mode_out |= ((flags & RUN_STDOUT_APPEND) ? O_APPEND : O_TRUNC);
  709.     mode_err |= ((flags & RUN_STDERR_APPEND) ? O_APPEND : O_TRUNC);
  710.  
  711.     if (stin && (shin = open (stin, O_RDONLY)) == -1)
  712.     {
  713.     rerrno = errno;
  714.     error (0, errno, "cannot open %s for reading (prog %s)",
  715.            stin, run_argv[0]);
  716.     goto out0;
  717.     }
  718.     if (stout && (shout = open (stout, mode_out, 0666)) == -1)
  719.     {
  720.     rerrno = errno;
  721.     error (0, errno, "cannot open %s for writing (prog %s)",
  722.            stout, run_argv[0]);
  723.     goto out1;
  724.     }
  725.     if (sterr && (flags & RUN_COMBINED) == 0)
  726.     {
  727.     if ((sherr = open (sterr, mode_err, 0666)) == -1)
  728.     {
  729.         rerrno = errno;
  730.         error (0, errno, "cannot open %s for writing (prog %s)",
  731.            sterr, run_argv[0]);
  732.         goto out2;
  733.     }
  734.     }
  735.  
  736.     /* The output files, if any, are now created.  Do the fork and dups */
  737. #ifdef VFORK_MISSING
  738.     pid = fork ();
  739. #else
  740.     pid = vfork ();
  741. #endif
  742.     if (pid == 0)
  743.     {
  744.     if (shin != 0)
  745.     {
  746.         (void) dup2 (shin, 0);
  747.         (void) close (shin);
  748.     }
  749.     if (shout != 1)
  750.     {
  751.         (void) dup2 (shout, 1);
  752.         (void) close (shout);
  753.     }
  754.     if (flags & RUN_COMBINED)
  755.         (void) dup2 (1, 2);
  756.     else if (sherr != 2)
  757.     {
  758.         (void) dup2 (sherr, 2);
  759.         (void) close (sherr);
  760.     }
  761.  
  762.     /* dup'ing is done.  try to run it now */
  763.     (void) execvp (run_argv[0], run_argv);
  764.     _exit (127);
  765.     }
  766.     else if (pid == -1)
  767.     {
  768.     rerrno = errno;
  769.     goto out;
  770.     }
  771.  
  772.     /* the parent.  Ignore some signals for now */
  773. #ifdef POSIX
  774.     if (flags & RUN_SIGIGNORE)
  775.     {
  776.     act.sa_handler = SIG_IGN;
  777.     (void) sigemptyset (&act.sa_mask);
  778.     act.sa_flags = 0;
  779.     (void) sigaction (SIGINT, &act, &iact);
  780.     (void) sigaction (SIGQUIT, &act, &qact);
  781.     }
  782.     else
  783.     {
  784.     (void) sigemptyset (&sigset_mask);
  785.     (void) sigaddset (&sigset_mask, SIGINT);
  786.     (void) sigaddset (&sigset_mask, SIGQUIT);
  787.     (void) sigprocmask (SIG_SETMASK, &sigset_mask, &sigset_omask);
  788.     }
  789. #else
  790. #ifdef BSD_SIGNALS
  791.     if (flags & RUN_SIGIGNORE)
  792.     {
  793.     bzero ((char *) &vec, sizeof (vec));
  794.     vec.sv_handler = SIG_IGN;
  795.     (void) sigvec (SIGINT, &vec, &ivec);
  796.     (void) sigvec (SIGQUIT, &vec, &qvec);
  797.     }
  798.     else
  799.     mask = sigblock (sigmask (SIGINT) | sigmask (SIGQUIT));
  800. #else
  801.     istat = signal (SIGINT, SIG_IGN);
  802.     qstat = signal (SIGQUIT, SIG_IGN);
  803. #endif
  804. #endif
  805.  
  806.     /* wait for our process to die and munge return status */
  807. #ifdef POSIX
  808.     while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR)
  809.     ;
  810. #else
  811.     while ((w = wait (&status)) != pid)
  812.     {
  813.     if (w == -1 && errno != EINTR)
  814.         break;
  815.     }
  816. #endif
  817.     if (w == -1)
  818.     {
  819.     status = -1;
  820.     rerrno = errno;
  821.     }
  822.     else if (WIFEXITED (status))
  823.     status = WEXITSTATUS (status);
  824.     else if (WIFSIGNALED (status))
  825.     {
  826.     if (WTERMSIG (status) == SIGPIPE)
  827.         error (1, 0, "broken pipe");
  828.     status = 2;
  829.     }
  830.     else
  831.     status = 1;
  832.  
  833.     /* restore the signals */
  834. #ifdef POSIX
  835.     if (flags & RUN_SIGIGNORE)
  836.     {
  837.     (void) sigaction (SIGINT, &iact, (struct sigaction *) NULL);
  838.     (void) sigaction (SIGQUIT, &qact, (struct sigaction *) NULL);
  839.     }
  840.     else
  841.     (void) sigprocmask (SIG_SETMASK, &sigset_omask, (sigset_t *) NULL);
  842. #else
  843. #ifdef BSD_SIGNALS
  844.     if (flags & RUN_SIGIGNORE)
  845.     {
  846.     (void) sigvec (SIGINT, &ivec, (struct sigvec *) NULL);
  847.     (void) sigvec (SIGQUIT, &qvec, (struct sigvec *) NULL);
  848.     }
  849.     else
  850.     (void) sigsetmask (mask);
  851. #else
  852.     (void) signal (SIGINT, istat);
  853.     (void) signal (SIGQUIT, qstat);
  854. #endif
  855. #endif
  856.  
  857.     /* cleanup the open file descriptors */
  858.   out:
  859.     if (sterr)
  860.     (void) close (sherr);
  861.   out2:
  862.     if (stout)
  863.     (void) close (shout);
  864.   out1:
  865.     if (stin)
  866.     (void) close (shin);
  867.  
  868.   out0:
  869.     if (rerrno)
  870.     errno = rerrno;
  871.     return (status);
  872. }
  873.  
  874. void
  875. run_print (fp)
  876.     FILE *fp;
  877. {
  878.     int i;
  879.  
  880.     for (i = 0; i < run_argc; i++)
  881.     {
  882.     (void) fprintf (fp, "%s", run_argv[i]);
  883.     if (i != run_argc - 1)
  884.         (void) fprintf (fp, " ");
  885.     }
  886. }
  887.  
  888. FILE *
  889. Popen (cmd, mode)
  890.     char *cmd, *mode;
  891. {
  892.     if (trace)
  893.     (void) fprintf (stderr, "-> Popen(%s,%s)\n", cmd, mode);
  894.     if (noexec)
  895.     return (NULL);
  896.     return (popen (cmd, mode));
  897. }
  898.  
  899. #ifdef lint
  900. #ifndef __GNUC__
  901. /* ARGSUSED */
  902. time_t
  903. get_date (date, now)
  904.     char *date;
  905.     struct timeb *now;
  906. {
  907.     time_t foo = 0;
  908.  
  909.     return (foo);
  910. }
  911. #endif
  912. #endif
  913.